---
title: 对象包装器与自动装箱
description: 对象包装器与自动装箱
---
## 对象包装器
有时，需要将 int 这样的基本类型转换为对象。所有的基本类型都有一个与之对应的类。这些类称为包装器（wrapper）。

Byte、Short、Integer、Long、Float、Double、Character、Boolean （前六个派生类属于公共类 Number）。包装器类是不可变的，即一旦构造了包装器，就不允许更改包装在其中的值。同时，包装器类还是 final ，因此不能派生它们的子类。

假设要定义一个整型数组列表，但尖括号中的类型参数不允许是基本类型，这里就需要用到包装器类。
```java
var list = new ArrayList<Integer>();
```
## 自动装箱
有一个很有用的特性，从而可以很容易地向 `ArrayList<Integer>` 添加 int 类型的元素。下面这个调用：
```java
list.add(3);
```
将自动转换成
```java
list.add(Integer.valueOf(3));
```
这种转换称为自动装箱（autoboxing）

反过来，当将一个 Integer 对象赋给一个 int 值时，将会自动拆箱（unboxed）。
```java
int n = list.get(i);
```
转换成
```java
int n = list.get(i).intValue()
```
自动装箱和自动拆箱也适用于算数表达式。
```java
Integer n = 3;
n ++;
```
编译器将自动地插入指令对对象拆箱，然后将结果值增一，最后再将其装箱。

== 运算符可以用于包装器对象，不过检测的是对象是否有相同的内存位置，因此，下面的比较会失败：
```java
Integer a = 1000;
Integer b = 1000;
System.out.println(a == b);
```
不过，Java 实现可以将经常出现的值包装到相同的对象中，这样一来，以上比较就可以成功，但充满了不确定性，解决的方法就是在比较两个包装器对象时调用 equals 方法。

:::tip
自动装箱规范要求 boolean、byte、char（`<=127`）,介于 -128 和 127 之间的 short 和 int 包装到固定的对象中。
:::
:::tip
绝对不要依赖包装器对象的同一性。不要使用 == 比较包装器对象，也不要将包装器对象作为锁。
:::
关于包装器对象还有几点说明。首先，由于包装器类引用可以为 null，所以自动装箱有可能会抛出一个 NullPointException 异常。
另外，如果在一个条件表达式中混合使用 Integer 和 Double ，则 Integer 值就会拆箱，提升为 double，再装箱为 Double。

装箱和拆箱是编译器要做的工作，而不是虚拟机。编译器生成类的字节码时会插入必要的方法调用。虚拟机只是执行这些方法。


## Integer
* int intValue()
* static String toString(int i)
* static String toString(int i,int radix) ： 返回数值 i 的一个表示（采用 radix 参数指定的进制）
* static int parseInt(String s)
* static int parseInt(String s,int radix)
* static Integer valueOf(String s)
* static Integer valueOf(String s,int radix)

## NumberFormat
* Number parse(String s): 返回一个数值。

